package com.pattern.structural.flyweight;

import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Use Ticket Query as an example
 * @author Ping
 * @date 2022/4/18 14:19
 **/
public class FlyWeightDemo {
    public static void main(String args[]) {
        Integer intger = 0 ;
        TicketDAO ticketDAO = new TicketDAO() ;
        String key = "FUZHOU_XIAMEN_14" ;
        for (int i=0; i<10000000; i++) {
            ticketDAO.query(key) ;
//            ticketDAO.queryByFW(key) ;
        }
        System.out.println("END OF QUERY") ;

    }
}


class Ticket {
    private String from ;
    private String to ;
    private String time ;
    private int leftAmount ;

    public Ticket(String from, String to, String time, int leftAmount) {
        this.from = from;
        this.to = to;
        this.time = time;
        this.leftAmount = leftAmount;
    }

}
class TicketDAO {
    Random random = new Random() ;

    /**
     * Query from DB
     * Key: "from_to_time"
     * @param key
     * @return
     */
    public Ticket query (String key) {
        String[] eles = key.split("_") ;
        /*
         assumming that the ticket infor was gotten from DB
         */
        return new Ticket(eles[0], eles[1], eles[2], random.nextInt(700)) ;
    }

    /**
     * Query based on flyweight
     * @param key
     * @return
     */
    public TicketFlyWeight queryByFW(String key) {
        return new TicketFlyWeight(TicketFlyWeightFactory.getTicketBasicInfor(key),
                      random.nextInt(700) );
    }

}

/**
 * the class storing from, to, time infor , these are basic infor for ticket and can
 * be shared.
 */
class TicketBasicInfor {
    private String from ;
    private String to ;
    private String time ;

    public TicketBasicInfor(String from, String to, String time) {
        this.from = from;
        this.to = to;
        this.time = time;
    }
}

class TicketFlyWeight {
    /**
     * Inner state
     */
    private TicketBasicInfor ticketBasic ;
    /**
     * extened state/dynamci and unsharable.
     */
    private int leftAmount ;

    public TicketFlyWeight(TicketBasicInfor ticketBasic, int leftAmount) {
        this.ticketBasic = ticketBasic;
        this.leftAmount = leftAmount;
    }
}

class TicketFlyWeightFactory {
    static Map<String, TicketBasicInfor> ticketInforMap = new ConcurrentHashMap<>() ;
    static {
        ticketInforMap.put("FUZHOU_XIAMEN_14",
                          new TicketBasicInfor("FUZHOU", "XIAMEN", "14") ) ;
    }
    public static TicketBasicInfor getTicketBasicInfor(String key) {
        return ticketInforMap.get(key) ;
    }
}